package com.xcc.core.lock;

import java.util.concurrent.CountDownLatch;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;

/**
 * 版权：(C) 版权所有 2019-2022  
 * <简述>
 * <详细描述>zookeeper 简单的排他锁，所之间进行竞争。
 * @author   xcc
 * @version  $Id$
 * @since
 * @see
 */
public   class ZKLock  extends AbstractLock{

    private static String CONNECT_PATH = "127.0.0.1:2181";

    protected ZkClient zkClient = new ZkClient(CONNECT_PATH);

    protected static final String PATH = "/lock";

    protected static final String PATH2 = "/lock2";
    private static final String NODE_NAME = "/test_simple_lock";

    private CountDownLatch countDownLatch;

    @Override
    public void releaseLock() {
        if (null != zkClient) {
            //删除节点
            zkClient.delete(NODE_NAME);
            zkClient.close();
            System.out.println(Thread.currentThread().getName()+"-释放锁成功");
        }

    }

    //直接创建临时节点，如果创建成功，则表示获取了锁,创建不成功则处理异常
    @Override
    public boolean tryLock() {
        if (null == zkClient) return false;
        try {
            zkClient.createEphemeral(NODE_NAME);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public void waitLock() {
        //监听器
        IZkDataListener iZkDataListener = new IZkDataListener() {
            //节点被删除回调
            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                if (countDownLatch != null) {
                    countDownLatch.countDown();
                }
            }
            //节点改变被回调
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {
            }
        };
        zkClient.subscribeDataChanges(NODE_NAME, iZkDataListener);
        //如果存在则阻塞
        if (zkClient.exists(NODE_NAME)) {
            countDownLatch = new CountDownLatch(1);
            try {
                countDownLatch.await();
                System.out.println(Thread.currentThread().getName()+" 等待获取锁...");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //删除监听
        zkClient.unsubscribeDataChanges(NODE_NAME, iZkDataListener);
    }

    public static void main(String[] args) {
        for (int i=0;i<10;i++) {
            Thread thread = new Thread(new LockRunnable());
            thread.start();
        }

    }
    static class LockRunnable implements Runnable{
        
        @Override
        public void run() {
            AbstractLock zkLock = new ZKLock();
            //AbstractLock zkLock = new HighPerformanceZkLock();
            zkLock.getLock();
            //模拟业务操作
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            zkLock.releaseLock();
        }
        
    }

}
